#include "ParamReader.h"

std::ifstream ParamReader::cfgFile; 

 double	ParamReader::GAMMA							=0.95;		//param:
 int		ParamReader::MAX_EPISODE_STEPS			=500;		//param:
 double	ParamReader::rmax							=0;			//param:	
 int		ParamReader::USE_GENERALIZATION_TIME	=1000;		//param: time when we start using generalization
 bool		ParamReader::LEARN_GENERALIZATION		=true;		//param:
 int		ParamReader::DELAY_DETECTION_TIME		=0;			//param: the time we fix k (negative number means prespecified k)
 bool		ParamReader::USE_GENERALIZATION			=true;		//param: are we using generalization or not
 int		ParamReader::USE_GENERALIZATION_END_TIME=-1;		//param: time we stop using generalization
 int		ParamReader::LEARN_GENERALIZATION_END_TIME	= -1; //param: when do we stop adding instances to FA
 bool		ParamReader::USE_DETERMINISTIC_POLICY	= 1;		//param: 
 bool		ParamReader::LOAD_MODEL					=0; 
 bool		ParamReader::SAVE_MODEL					=0;
 int		ParamReader::RMAX_KNOWN_THRESHOLD		=1; 

 int		ParamReader::EST_SAMPLE_SIZE			=5;			//param: number of samples we pick from our generalizers when we try to appx a transition
 int		ParamReader::DISCRETIZED_SIZE			=40 ; 		//param:how many cells per continuous dimension should we have
 int		ParamReader::SOLVE_PERIOD				=300;		//param: interval for solving our model
 int		ParamReader::BATCH_LEARNING_TIME		=200;		//param:
 int		ParamReader::BATCH_LEARNING_END_TIME	= 3000;		//param:
 int		ParamReader::RUN_TIMEOUT				=100;		//param: 
 double		ParamReader::VI_EPSILON					= 0.001;	//param: when value iteration stops
 int		ParamReader::NUMBER_OF_VI_SAMPLES		=30;		//how many samples per dimension
 int		ParamReader::MULTISTEP_BACKUP_HORIZON   =4; 
 bool ParamReader::load(const char * fname)
 {
	 try{
	 cfgFile.open(fname); 
	 }
	 catch(...)
	 {
		return false; 
	 }
	 if (! cfgFile.is_open())
		 return false; 
	readDouble("GAMMA",ParamReader::GAMMA); 
	readInt("MAX_EPISODE_STEPS",ParamReader::MAX_EPISODE_STEPS); 
	readDouble("rmax",ParamReader::rmax); 
	readInt("EST_SAMPLE_SIZE",ParamReader::EST_SAMPLE_SIZE); 
	readInt("USE_GENERALIZATION_TIME",ParamReader::USE_GENERALIZATION_TIME); 
	readInt("USE_GENERALIZATION_END_TIME", ParamReader::USE_GENERALIZATION_END_TIME); 
	readBool("USE_GENERALIZATION",ParamReader::USE_GENERALIZATION); 
	readInt("DELAY_DETECTION_TIME",ParamReader::DELAY_DETECTION_TIME); 
	readInt("DISCRETIZED_SIZE",ParamReader::DISCRETIZED_SIZE); 
	readInt("SOLVE_PERIOD",ParamReader::SOLVE_PERIOD); 
	readBool("LEARN_GENERALIZATION", ParamReader::LEARN_GENERALIZATION); 
	readInt("BATCH_LEARNING_TIME", ParamReader::BATCH_LEARNING_TIME); 
	readInt("RUN_TIMEOUT", ParamReader::RUN_TIMEOUT); 
	readInt("LEARN_GENERALIZATION_END_TIME", ParamReader::LEARN_GENERALIZATION_END_TIME); 
	readDouble("VI_EPSILON", ParamReader::VI_EPSILON); 
	readBool("USE_DETERMINISTIC_POLICY", ParamReader::USE_DETERMINISTIC_POLICY); 
	readInt("BATCH_LEARNING_END_TIME", ParamReader::BATCH_LEARNING_END_TIME); 
	readBool("LOAD_MODEL", ParamReader::LOAD_MODEL); 
	readBool("SAVE_MODEL", ParamReader::SAVE_MODEL); 
readInt("RMAX_KNOWN_THRESHOLD", ParamReader::RMAX_KNOWN_THRESHOLD); 
	readInt("NUMBER_OF_VI_SAMPLES", ParamReader::NUMBER_OF_VI_SAMPLES); 
	readInt("MULTISTEP_BACKUP_HORIZON", ParamReader::MULTISTEP_BACKUP_HORIZON); 
cfgFile.close(); 
	return true; 
 }

void ParamReader::print()
{
printf("---------params---------------\n"); 
	printf("GAMMA\t%lf \n",ParamReader::GAMMA ); 
	printf("MAX_EPISODE_STEPS\t%d \n", ParamReader::MAX_EPISODE_STEPS); 
	printf("rmax\t%lf \n", ParamReader::rmax); 
	printf("EST_SAMPLE_SIZE\t%d \n",ParamReader::EST_SAMPLE_SIZE ); 
	printf("USE_GENERALIZATION_TIME\t%d \n",ParamReader::USE_GENERALIZATION_TIME ); 
	printf("USE_GENERALIZATION_END_TIME\t%d \n", ParamReader::USE_GENERALIZATION_END_TIME); 
	printf("USE_GENERALIZATION\t%d \n",ParamReader::USE_GENERALIZATION ); 
	printf("LEARN_GENERALIZATION\t%d \n", ParamReader::LEARN_GENERALIZATION); 
	printf("BATCH_LEARNING_END_TIME\t%d \n", ParamReader::BATCH_LEARNING_END_TIME); 
	printf("BATCH_LEARNING_TIME\t%d \n", ParamReader::BATCH_LEARNING_TIME); 
	printf("DELAY_DETECTION_TIME\t%d \n",ParamReader::DELAY_DETECTION_TIME ); 
	printf("DISCRETIZED_SIZE\t%d \n",ParamReader::DISCRETIZED_SIZE ); 
	printf("SOLVE_PERIOD\t%d \n",ParamReader::SOLVE_PERIOD ); 
	printf("LEARN_GENERALIZATION_END_TIME\t%d \n", ParamReader::LEARN_GENERALIZATION_END_TIME); 
	printf("VI_EPSILON\t%lf \n", VI_EPSILON); 
	printf("USE_DETERMINISTIC_POLICY\t%d \n", USE_DETERMINISTIC_POLICY); 
	printf("LOAD_MODEL\t%d	\n", LOAD_MODEL); 
	printf("SAVE_MODEL\t%d	\n", SAVE_MODEL); 
	printf("RMAX_KNOWN_THRESHOLD\t%d\t\n", RMAX_KNOWN_THRESHOLD); 
	printf("NUMBER_OF_VI_SAMPLES\t%d \n", NUMBER_OF_VI_SAMPLES); 
	printf("MULTISTEP_BACKUP_HORIZON\t%d \n", MULTISTEP_BACKUP_HORIZON); 
	printf("------------------------------\n"); 



 }


//! returns true if the (0-terminated) string s contains c 
  inline bool contains(const char* s,char c){
    for(int i=0;s[i];i++) if(s[i]==c) return true;
    return false;
  }

  //! skips the chars (typically white characters) when parsing from the istream
  inline char skip(std::istream& is,char* skipchars){
    char c;
    do{ c=is.get(); } while(contains(skipchars,c));
    is.putback(c);
    return c;
  }



char ParamReader::getNextChar(std::ifstream& cfg)
{
	if (! cfg.good())
		return '\n';

	char c = cfg.get(); 
	if (c == '#') 
	{
		while (cfg.good())
		{
			c = cfg.get(); 
			if (c == '\n')
				return c; 
		}
		return '\n'; 
	}
	return c; 
}


bool ParamReader::skip2param(const char* tag)
{
	cfgFile.clear();
	cfgFile.seekg(std::ios::beg);
	if(!cfgFile.good()) return false;

	unsigned n=strlen(tag);
	char *buf=new char [n+2]; memset(buf,0,n+2);
	while(cfgFile.good()){
		memmove(buf,buf+1,n);
		buf[n]=getNextChar(cfgFile); 

		if (buf[n] =='#') 
			skip(cfgFile,"\n"); 
		if(buf[n]==' ' || buf[n]=='\t' || buf[n]==':' || buf[n]=='=')
		{ 
			buf[n]=0; 
			if(!strcmp(tag,buf)) 
				break; 
			buf[n]=':'; 
		}
	};
	delete[] buf;

	if(!cfgFile.good()) return false;

	skip(cfgFile," :=\n\r\t");

	return true; 
}

int ParamReader::readInt(const char* tag, int& value)
{

	if (skip2param(tag))
		cfgFile >>value;

	return value; 
}


double ParamReader::readDouble(const char* tag, double& value)
{

	if (skip2param(tag))
		cfgFile >>value;

	return value; 
}


char* ParamReader::readString(const char* tag, char*& value)
{

	if (skip2param(tag))
	cfgFile >>value;

	return value; 
}

bool ParamReader::readBool(const char* tag, bool& value)
{

	if (skip2param(tag))
		cfgFile >>value;

	return value; 
}

